import React,{PropTypes,Component} from 'react';
import {render} from 'react-dom';
import {Provider,connect} from "react-redux";
import {createStore,applyMiddleware,combineReducers} from "redux";
import thunk from "redux-thunk";
import createLogger from "redux-logger";
const REQUEST_POSTS = 'REQUEST_POSTS';
const RECEIVE_POSTS = 'RECEIVE_POSTS';
const SELECT_REDDIT = 'SELECT_REDDIT';
const INVALIDATE_REDDIT = 'INVALIDATE_REDDIT';

const selectReddit=reddit=>({
    type:SELECT_REDDIT,
    reddit
})
const invalidateReddit=reddit=>({
    type:INVALIDATE_REDDIT,
    reddit
})
const requestPosts=reddit=>({
    type:REQUEST_POSTS,
    reddit
})
const receivePosts=(reddit,json)=>({
    type:RECEIVE_POSTS,
    reddit,
    posts:json.data.children.map(child=>child.data),
    receivedAt:Date.now()
})
const fetchPosts=reddit=>dispatch=>{
    dispatch(requestPosts(reddit))
    return fetch(`https://www.reddit.com/r/${reddit}.json`)
        .then(response=>response.json())
        .then(json=>dispatch(receivePosts(reddit,json)))
}
const shouldFetchPosts=(state,reddit)=>{
    const posts=state.postsByReddit[reddit]
    if(!posts){
        return true
    }
    if(posts.isFetching){
        return false
    }
    return posts.didInvalidate
}
const fetchPostsIfNeeded=reddit=>(dispatch,getState)=>{
    if(shouldFetchPosts(getState(),reddit)){
        return dispatch(fetchPosts(reddit))
    }
}

const selectedReddit=(state="reactjs",action)=>{
    switch(action.type){
        case SELECT_REDDIT:
            return action.reddit
        default:
            return state
    }
}

const posts = (state = {
  isFetching: false,
  didInvalidate: false,
  items: []
}, action) => {
  switch (action.type) {
    case INVALIDATE_REDDIT:
      return {
        ...state,
        didInvalidate: true
      }
    case REQUEST_POSTS:
      return {
        ...state,
        isFetching: true,
        didInvalidate: false
      }
    case RECEIVE_POSTS:
      return {
        ...state,
        isFetching: false,
        didInvalidate: false,
        items: action.posts,
        lastUpdated: action.receivedAt
      }
    default:
      return state
  }
}

const postsByReddit=(state={},action)=>{
    switch(action.type){
        case INVALIDATE_REDDIT:
        case RECEIVE_POSTS:
        case REQUEST_POSTS:
            return {
                ...state,
                [action.reddit]:posts(state[action.reddit],action)
            }
            default:
                return state
    }
}
//待理解
const reducer=combineReducers({
    postsByReddit,
    selectedReddit
});

const middleware=[thunk];
if(process.env.NODE_ENV!=='production'){
    middleware.push(createLogger())
};

const store=createStore(
    reducer,
    applyMiddleware(...middleware)
);


const Picker=({value,onChange,options})=>(
        <span>
            <h1>{value}</h1>
            <select onChange={e=>onChange(e.target.value)} value={value}>
                {options.map(option=>
                    <option value={option} key={option}>
                        {option}
                    </option>
                )
                }
            </select>
        </span>
    );
Picker.PropTypes={
    options:PropTypes.arrayOf(
        PropTypes.string.isRequired
    ).isRequired,
    value:PropTypes.string.isRequired,
    onChange:PropTypes.func.isRequired
};

const Posts=({posts})=>(
    <ul>
    {
    posts.map((post,i)=>
        <li key={i}>{post.title}</li>
    )
    }
</ul>
);
Posts.propTypes={
    posts:PropTypes.array.isRequired
};

class AppUi extends Component{
    static propTypes={
        selectedReddit:PropTypes.string.isRequired,
        posts:PropTypes.array.isRequired,
        isFetching:PropTypes.bool.isRequired,
        lastUpdated:PropTypes.number,
        dispatch:PropTypes.func.isRequired
    };

    componentDidMount(){
        const {dispatch,selectedReddit}=this.props;
        dispatch(fetchPostsIfNeeded(selectedReddit))
    };
    // 待理解
    componentWillReceiveProps(nextProps){
        if(nextProps.selectedReddit!==this.props.selectedReddit){
            const{dispatch,selectedReddit}=nextProps;
            dispatch(fetchPostsIfNeeded(selectedReddit));
        }
    };
    // 待理解

    handleChange=nextReddit=>{
        this.props.dispatch(selectReddit(nextReddit))
    }
    // 待理解
    handleRefreshClick=e=>{
        e.preventDefault();
        const {dispatch,selectedReddit}=this.props;
        dispatch(invalidateReddit(selectedReddit));
        dispatch(fetchPostsIfNeeded(selectedReddit));
    }
    // 待理解
    render(){
        const {selectedReddit,posts,isFetching,lastUpdated}=this.props;
                const isEmpty=posts.lengths===0;
                return(
                    <div>
                        <Picker value={selectedReddit} onChange={this.handleChange} options={["reactjs","frontend"]}/>
                        <p>
                            {lastUpdated && 
                                <span>
                                    Last updated at {new Date(lastUpdated).toLocaleTimeString()}.{" "}
                                </span>
                            }
                            {
                            !isFetching && 
                                <a href="#" onClick={this.handleRefreshClick}>Refresh</a>
                            }
                        </p>
                        {isEmpty
                        ?(isFetching?<h2>Loading...</h2>:<h2>Empty.</h2>)
                        :<div style={{opacity:isFetching?0.5:1}}>
                            <Posts posts={posts} />
                        </div>
                        }
                    </div>
                )
    }
}

const mapStateToProps=state=>{
    const {selectedReddit,postsByReddit}=state;
    const{
        isFetching,
        lastUpdated,
        items:posts
        }
        =
        postsByReddit[selectedReddit]||{
            isFetching:true,
            items:[]
        }
    return {
        selectedReddit,
        posts,
        isFetching,
        lastUpdated
    }
}
const App=connect(mapStateToProps)(AppUi);


//待理解

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
